Skip to content

Introduce ActionRunAttempt to represent each execution of a run#37119

Draft
Zettat123 wants to merge 34 commits intogo-gitea:mainfrom
Zettat123:run-attempt
Draft

Introduce ActionRunAttempt to represent each execution of a run#37119
Zettat123 wants to merge 34 commits intogo-gitea:mainfrom
Zettat123:run-attempt

Conversation

@Zettat123
Copy link
Copy Markdown
Contributor

@Zettat123 Zettat123 commented Apr 6, 2026

This PR introduces a new ActionRunAttempt model and makes Actions execution attempt-scoped.

Main Changes

  • Each workflow run trigger generates a new ActionRunAttempt. The triggered jobs are then associated with this new ActionRunAttempt record.
  • Each rerun now creates:
    • a new ActionRunAttempt record for the workflow run
    • a full new set of ActionRunJob records for the new ActionRunAttempt
      • For jobs that need to be rerun, the new job records are created as runnable jobs in the new attempt.
      • For jobs that do not need to be rerun, new job records are still created in the new attempt, but they reuse the result of the previous attempt instead of executing again.
  • Introduce rerunPlan to manage each rerun and refactored rerun flow into a two-phase plan-based model:
    • buildRerunPlan
    • execRerunPlan
  • Converted artifacts from run-scoped to attempt-scoped:
    • uploads are now associated with RunAttemptID
    • listing, download, and deletion resolve against the current attempt
  • Added attempt-aware web Actions views:
    • the default run page shows the latest attempt (/actions/runs/{run_id})
    • previous attempt pages show jobs and artifacts for that attempt (/actions/runs/{run_id}/attempts/{attempt_num})
  • New APIs:
    • /repos/{owner}/{repo}/actions/runs/{run}/attempts/{attempt}
    • /repos/{owner}/{repo}/actions/runs/{run}/attempts/{attempt}/jobs

Compatibility

  • Existing legacy runs use LatestAttemptID = 0 and legacy jobs use RunAttemptID = 0. Therefore, these fields can be used to identify legacy runs and jobs and provide backward compatibility.
  • Existing artifact records are not backfilled; legacy artifacts continue to use RunAttemptID = 0.

Improvements

  • It is now easier to inspect and download logs from previous attempts.
  • run_attempt semantics are now aligned with GitHub.
    • A unique number for each attempt of a particular workflow run in a repository. This number begins at 1 for the workflow run's first attempt, and increments with each re-run.

  • Rerun behavior is now clearer and more explicit.
    • Instead of mutating the status of previous jobs in place, each rerun creates a new attempt with a full new set of job records.
  • Artifacts produced by different reruns can now be listed separately.

TODO

  • Support query run/job by attempt via API
  • Improve tests
    • concurrency
    • rerun
    • artifacts
    • new APIs
Screenshots

Run with only one attempt:

image

Rerunning:

image

Latest attempt:

image

Previous attempt (rerun is not allowed):

image

Dropdown for attempt records:

image

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Apr 6, 2026
@github-actions github-actions bot added modifies/api This PR adds API routes or modifies them modifies/go Pull requests that update Go code modifies/templates This PR modifies the template files modifies/migrations modifies/frontend labels Apr 6, 2026
@Zettat123 Zettat123 added the topic/gitea-actions related to the actions of Gitea label Apr 6, 2026
@Zettat123 Zettat123 force-pushed the run-attempt branch 2 times, most recently from 3da69e5 to 7f338dd Compare April 6, 2026 05:11
return err
}

run.LatestAttemptID = runAttempt.ID
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UpdateRunAttempt calls UpdateRun again to sync status/started/stopped. That's three writes to action_run inside one transaction.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I’ve noticed that issue as well. In this function, we need to create/update the same ActionRun record three times.

  1. Create the ActionRun to get ActionRun.ID
  2. Use ActionRun.ID to create a RunAttempt and write RunAttempt.ID back to ActionRun.LatestAttemptID
  3. After all the jobs are created, update ActionRun.Status (via UpdateRunAttempt)

I'm not sure of a better way to handle this yet - any ideas are welcome.

@Zettat123 Zettat123 changed the title Introduce RunAttempt to represent each execution of a run Introduce ActionRunAttempt to represent each execution of a run Apr 6, 2026
@silverwind
Copy link
Copy Markdown
Member

silverwind commented Apr 7, 2026

  1. Would order buttons like [attempt] [re-run all]. People are use to buttons being at the same places.
  2. Hide the button on first attempt, only show on subsequent ones (maybe that's already the case).

@silverwind
Copy link
Copy Markdown
Member

Two concerns worth addressing:

1. Race condition on concurrent reruns

Two simultaneous rerun requests for the same run both read templateAttempt.Attempt and try to insert an attempt with Attempt = templateAttempt.Attempt + 1. The UNIQUE(run_attempt) constraint catches this at the DB level, but the error surfaces as an internal server error rather than a clean user-facing message. A retry or ErrAlreadyExists check in execRerunPlan would be a small fix with real UX impact.

2. RecreateTables on action_artifact in migration v331

base.RecreateTables(new(actionArtifact)) copies the entire table to change the unique index from runid_name_path to runid_attempt_name_path. On large instances this locks the table for the duration of a full data copy. If the only goal is renaming the unique index and adding the run_attempt_id column, a lighter migration (add column, drop old index, create new index) would be much safer in production.


This comment was written by Claude Opus 4.6.

@silverwind
Copy link
Copy Markdown
Member

silverwind commented Apr 7, 2026

A few inconsistencies with GitHub's behavior:

1. actor vs triggering_actor semantics

On GitHub, actor is the person who originally triggered the workflow and stays constant across all attempts. triggering_actor is the person who initiated each specific attempt and changes on rerun. In this PR, ToActionWorkflowRun sets both fields to the attempt's trigger user.

Example from GitHub (cli/cli run 23574913305):

  • Attempt 1: actor=mateenali66, triggering_actor=mateenali66
  • Attempt 2: actor=mateenali66, triggering_actor=williammartin

The actor should remain run.TriggerUser regardless of which attempt is being viewed.

2. Missing previous_attempt_url field

GitHub's workflow run response includes previous_attempt_url which links to the API endpoint of the prior attempt (e.g. .../runs/123/attempts/1 for attempt 2, null for attempt 1). This field is absent from Gitea's ActionWorkflowRun struct.

3. Attempt switcher label differs from GitHub

On GitHub, the dropdown button shows just Latest when viewing the latest attempt. The PR currently shows Latest attempt #N. The dropdown items should show Attempt #N for all entries. Only the button text for the current latest should be just Latest.


This comment was written by Claude Opus 4.6.

Zettat123 and others added 5 commits April 7, 2026 15:05
@wxiaoguang
Copy link
Copy Markdown
Contributor

/devtest/repo-action-view can also be updated, then more edge cases can be easily tested without really setting up an Actions run.

@Zettat123
Copy link
Copy Markdown
Contributor Author

  1. Would order buttons like [attempt] [re-run all]. People are use to buttons being at the same places.
  1. Hide the button on first attempt, only show on subsequent ones (maybe that's already the case).

Attempt switcher label differs from GitHub

Fixed by 7c8e2a8. Please see the latest screenshots in description.

Race condition on concurrent reruns

9dafc83

RecreateTables on action_artifact in migration v331

d1d6b5c

actor vs triggering_actor semantics

8c5c5b9

Missing previous_attempt_url field

3d488fb

@Zettat123
Copy link
Copy Markdown
Contributor Author

/devtest/repo-action-view can also be updated, then more edge cases can be easily tested without really setting up an Actions run.

Updated /devtest/repo-action-view in f354e00

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. modifies/api This PR adds API routes or modifies them modifies/frontend modifies/go Pull requests that update Go code modifies/migrations modifies/templates This PR modifies the template files topic/gitea-actions related to the actions of Gitea

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants